<template>
  <view class="tn-scroll-list" :style="wrapperStyle">
    <scroll-view
        class="tn-scroll-view"
        :scroll-x="scrollX"
        :scroll-y="scrollY"
        :scroll-left="innerScrollLeft"
        :scroll-top="innerScrollTop"
        :scroll-with-animation="scrollWithAnimation"
        @scroll="handleScroll"
        @scrolltoupper="handleScrollToUpper"
        @scrolltolower="handleScrollToLower"
    >
      <view class="tn-scroll-content" :style="contentStyle">
        <slot />
      </view>
    </scroll-view>
  </view>
</template>

<script setup lang="ts">
import { ref, watch, nextTick, onMounted, computed } from "vue";

interface Props {
  width?: string | number; // 容器宽度
  height?: string | number; // 容器高度
  scrollX?: boolean; // 横向滚动
  scrollY?: boolean; // 纵向滚动
  scrollLeft?: number; // 初始横向滚动距离
  scrollTop?: number; // 初始纵向滚动距离
  gap?: string | number; // 子项之间的间距
  scrollWithAnimation?: boolean; // 是否开启动画
}

const props = withDefaults(defineProps<Props>(), {
  width: "100vw",
  height: "auto",
  scrollX: true,
  scrollY: false,
  scrollLeft: 0,
  scrollTop: 0,
  gap: 0,
  scrollWithAnimation: true
});

const emits = defineEmits(["scroll", "scrolltoupper", "scrolltolower"]);

const innerScrollLeft = ref(0);
const innerScrollTop = ref(0);

// 容器样式
const wrapperStyle = computed(() => {
  return `
    width: ${typeof props.width === "number" ? props.width + "px" : props.width};
    height: ${typeof props.height === "number" ? props.height + "px" : props.height};
  `;
});

// 子项容器样式
const contentStyle = computed(() => {
  return `
    display: flex;
    flex-direction: ${props.scrollX ? "row" : "column"};
    gap: ${typeof props.gap === "number" ? props.gap + "px" : props.gap};
  `;
});

// 监听外部传入的 scrollLeft 和 scrollTop
watch(
    () => props.scrollLeft,
    (val) => {
      nextTick(() => {
        innerScrollLeft.value = val;
      });
    },
    { immediate: true }
);

watch(
    () => props.scrollTop,
    (val) => {
      nextTick(() => {
        innerScrollTop.value = val;
      });
    },
    { immediate: true }
);

const handleScroll = (e: any) => emits("scroll", e);
const handleScrollToUpper = () => emits("scrolltoupper");
const handleScrollToLower = () => emits("scrolltolower");

// 组件挂载后初始化滚动位置
onMounted(() => {
  nextTick(() => {
    innerScrollLeft.value = props.scrollLeft;
    innerScrollTop.value = props.scrollTop;
  });
});
</script>

<style scoped>
.tn-scroll-list {
  display: flex;
  overflow: hidden;
  padding-right: 40px;
}

.tn-scroll-view {
  width: 100%;
  height: 100%;
  white-space: nowrap;
}

.tn-scroll-content {
  display: flex;
  align-items: center;
}
</style>
